package selenium.edge;

import lombok.Data;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.NumberToTextConverter;
import org.openqa.selenium.*;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.interactions.Actions;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Data
@SuppressWarnings("unchecked")
public class SeleniumEdgeTest {
    private WebDriver driver;
    private JavascriptExecutor js;
    private Map<String, Object> vars;

    public SeleniumEdgeTest(String driverPath) {
        System.setProperty("webdriver.edge.driver", driverPath);
        this.driver = new EdgeDriver();
        this.js = (JavascriptExecutor) driver;
        this.vars = new HashMap<>();
    }

    /**
     * 关闭
     */
    public void close() {
        driver.quit();
    }

    /**
     * 等待新页面
     */
    private String waitForWindow() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Set<String> whNow = driver.getWindowHandles();
        Set<String> whThen = (Set<String>) vars.get("window_handles");
        if (whNow.size() > whThen.size()) {
            whNow.removeAll(whThen);
        }
        return whNow.iterator().next();
    }

    /**
     * 编排脚本
     */
    public void run(String account, String password, String clazzNo, String resultFile) {
        // 登录
        login(account, password);
        // 菜单
        menu();
        // 班级
        classes(clazzNo);
        // 成绩
        loadResult(resultFile);
    }

    /**
     * 读属性
     */
    private static Map<String, String> readProperty(String propertyFile) {
        Map<String, String> result = new HashMap<>(10);
        Properties prop = new Properties();
        try {
            BufferedReader bf = new BufferedReader(new InputStreamReader(new FileInputStream(propertyFile), StandardCharsets.UTF_8));
            prop.load(bf);
            for (String key : prop.stringPropertyNames()) {
                result.put(key, prop.getProperty(key));
            }
            bf.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 读取excel重的成绩
     */
    private Map<String, String[]> readExcelFile(String excelFile) {
        Map<String, String[]> result = new HashMap<>(100);
        try {

            //1、获取文件输入流
            InputStream inputStream = new FileInputStream(excelFile);
            //2、获取Excel工作簿对象
            HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
            //3、得到Excel工作表对象
            HSSFSheet sheetAt = workbook.getSheetAt(0);
            //4、循环读取表格数据
            for (Row row : sheetAt) {
                //首行（即表头）不读取
                if (row.getRowNum() == 0 || row.getRowNum() == 1) {
                    continue;
                }
                // 学号
                String code = getStringFromCell(row.getCell(0));
                // 平时成绩
                String result1 = getStringFromCell(row.getCell(5));
                // 期末成绩
                String result2 = getStringFromCell(row.getCell(7));
                result.put(code, new String[]{result1, result2});
            }
            //5、关闭流
            workbook.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 获取单元格内容，字符串形式返回
     */
    private String getStringFromCell(Cell cell) {
        if (cell == null) {
            return "";
        }
        if (CellType.STRING == cell.getCellType()) {
            return cell.getStringCellValue().trim();
        } else if (CellType.NUMERIC == cell.getCellType()) {
            return NumberToTextConverter.toText(cell.getNumericCellValue());
        } else {
            return cell.toString();
        }
    }

    /**
     * 录入成绩
     */
    private void loadResult(String excelFile) {
        Map<String, String[]> name2ResultMap = readExcelFile(excelFile);

        // 24 | selectFrame | index=0 |
        vars.put("win1701", waitForWindow());
        // 25 | click | id=CHKPSCJ2 |
        driver.switchTo().window(vars.get("win1701").toString());
        // 26 | click | id=CHKPSCJ1 |
        driver.switchTo().frame(0);
        // 27 | type | id=CHKPSCJ1 | 100
        List<WebElement> trs = driver.findElements(By.cssSelector("form[name='form1'] table tr.B,.H"));
        for (WebElement tr : trs) {
            String code = tr.findElement(By.cssSelector("td:nth-child(2)")).getText().trim();
            String[] result = name2ResultMap.get(code);
            if (result == null) {
                continue;
            }
            WebElement input0 = tr.findElements(By.cssSelector("td.CJTD")).get(0).findElement(By.cssSelector("input"));
            WebElement input2 = tr.findElements(By.cssSelector("td.CJTD")).get(2).findElement(By.cssSelector("input"));
            if (!"true".equalsIgnoreCase(input0.getAttribute("readonly"))) {
                input0.sendKeys(result[0]);
            }
            if (!"true".equalsIgnoreCase(input2.getAttribute("readonly"))) {
                input2.sendKeys(result[1]);
            }
        }
    }

    /**
     * 选择班级
     */
    private void classes(String clazzNo) {
        // 19 | selectFrame | index=0 |
        driver.switchTo().frame(0);
        // 20 | click | id=button |
        driver.findElement(By.id("button")).click();
        // 21 | selectFrame | index=0 |
        driver.switchTo().frame(0);
        // 22 | click | css=.B:nth-child(1) > .AT |
        vars.put("window_handles", driver.getWindowHandles());
        // 23 | selectWindow | handle=${win1701} |
        List<WebElement> trs = driver.findElements(By.cssSelector(".B,.H"));
        for (WebElement tr : trs) {
            String text = tr.findElements(By.cssSelector("td")).get(3).getText();
            if (text.equalsIgnoreCase(clazzNo)) {
                tr.findElement(By.cssSelector(".AT")).click();
                break;
            }
        }
    }

    /**
     * 选择菜单
     */
    private void menu() {
        // 可能会弹出“已在别处退出登录”的弹出框，点击确定
        try {
            driver.switchTo().alert().accept();
        } catch (Exception e) {
            // 没有就忽略
        }
        // 14 | selectFrame | relative=parent |
        driver.switchTo().defaultContent();
        // 15 | selectFrame | index=2 |
        driver.switchTo().frame(2);
        // 16 | click | css=#memuBarText5 > b |
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        driver.findElement(By.cssSelector("#memuBarText5 > b")).click();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 17 | click | css=#memuLinkDiv5 > table > tbody > tr:nth-child(3) > td:nth-child(2) |
        driver.findElement(By.cssSelector("#memuLinkDiv5 > table > tbody > tr:nth-child(3) > td:nth-child(2)")).click();
        // 18 | click | css=#divGrpC0502 tr:nth-child(2) > td:nth-child(2) |
        driver.findElement(By.cssSelector("#divGrpC0502 tr:nth-child(2) > td:nth-child(2)")).click();
    }

    /**
     * 登录
     */
    private void login(String account, String password) {
        // 1 | open | /index.aspx |
        driver.get("http://jw.zfc.edu.cn/index.aspx");
        // 2 | setWindowSize | 1270x680 |
        driver.manage().window().setSize(new Dimension(1270, 680));
        // 3 | selectFrame | index=0 |
        driver.switchTo().frame(0);
        // 4 | click | name=Sel_Type |
        driver.findElement(By.name("Sel_Type")).click();
        // 5 | select | name=Sel_Type | label=教师教辅人员
        {
            WebElement dropdown = driver.findElement(By.name("Sel_Type"));
            dropdown.findElement(By.xpath("//option[. = '教师教辅人员']")).click();
        }
        // 6 | click | id=txt_asmcdefsddsd |
        driver.findElement(By.id("txt_asmcdefsddsd")).click();
        // 7 | type | id=txt_asmcdefsddsd | 20210040
        driver.findElement(By.id("txt_asmcdefsddsd")).sendKeys(account);
        // 8 | click | css=tr:nth-child(2) > td:nth-child(2) |
        driver.findElement(By.cssSelector("tr:nth-child(2) > td:nth-child(2)")).click();
        // 9 | mouseDown | id=txt_psasas |
        {
            WebElement element = driver.findElement(By.id("txt_psasas"));
            Actions builder = new Actions(driver);
            builder.moveToElement(element).clickAndHold().perform();
        }
        // 10 | mouseUp | id=txt_pewerwedsdfsdff |
        {
            WebElement element = driver.findElement(By.id("txt_pewerwedsdfsdff"));
            Actions builder = new Actions(driver);
            builder.moveToElement(element).release().perform();
        }
        // 11 | click | css=tr:nth-child(3) > td:nth-child(2) |
        driver.findElement(By.cssSelector("tr:nth-child(3) > td:nth-child(2)")).click();
        // 12 | type | id=txt_pewerwedsdfsdff | ***
        driver.findElement(By.id("txt_pewerwedsdfsdff")).sendKeys(password);
        // 13 | click | id=btn_login |
        driver.findElement(By.id("btn_login")).click();
    }

    public static void main(String[] args) {
        Map<String, String> properties = readProperty("config.properties");
        SeleniumEdgeTest test = new SeleniumEdgeTest(properties.get("edgeDriverPath"));
        test.run(properties.get("account"), properties.get("password"), properties.get("clazzNo"), properties.get("excelPath"));
    }
}
